package orm

import (
	"time"

	"gitee.com/xiawucha365/sago.v2/core/config"
	"github.com/garyburd/redigo/redis"
)

type DbRedis struct {
	conn *redis.Pool
}

func NewRedis(cf *config.Config) *DbRedis {

	dbredis := new(DbRedis)
	dbredis.conn = &redis.Pool{
		//连接池控制
		//Wait:        true,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", cf.Redis.Addr,
				redis.DialConnectTimeout(time.Second*10),
				redis.DialPassword(cf.Redis.Password))
			if err != nil {
				panic(err)
			} else {
				return c, nil
			}

		},
	}
	//连接池数量
	dbredis.conn.MaxIdle = 100
	dbredis.conn.MaxActive = 50
	dbredis.conn.IdleTimeout = 2 * time.Second
	return dbredis
}

func (m *DbRedis) Close() (err error) {
	return m.conn.Close()
}

func (m *DbRedis) Del(key string) (err error) {
	con := m.conn.Get()
	defer con.Close()

	_, err = con.Do("DEL", key)
	return
}

func (m *DbRedis) Set(key string, val string) (err error) {
	con := m.conn.Get()
	defer con.Close()
	if _, err := con.Do("SET", key, val); err != nil {
		return err
	}
	return nil
}

func (m *DbRedis) Get(key string) (reply string, err error) {
	con := m.conn.Get()
	defer con.Close()
	if reply, err := redis.String(con.Do("GET", key)); err != nil {
		return "", err
	} else {
		return reply, err
	}
}

//list 操作
func (m *DbRedis) LPushBatch(queueName string, keys []string) (err error) {
	if len(keys) == 0 {
		return
	}
	con := m.conn.Get()
	defer con.Close()
	_, err = con.Do("lpush", redis.Args{}.Add(queueName).AddFlat(keys)...)
	return
}

func (m *DbRedis) LPush(queueName string, key string) (err error) {
	if key == "" {
		return
	}
	con := m.conn.Get()
	defer con.Close()
	_, err = con.Do("lpush", queueName, key)
	return
}

func (m *DbRedis) BRPop(queueName string, timeout int) (data string, err error) {
	con := m.conn.Get()
	defer con.Close()
	nameAndData, err := redis.Strings(con.Do("brpop", queueName, timeout))
	if err != nil && err == redis.ErrNil {
		err = nil
		return
	}
	if len(nameAndData) > 1 {
		data = nameAndData[1]
	}
	return
}

//sortset 有序集合操作

func (m *DbRedis) ZIncr(setname string, member string) (err error) {
	con := m.conn.Get()
	defer con.Close()
	_, err = con.Do("zincrby", setname, 1, member)

	return
}

func (m *DbRedis) ZRangeAsc(setname string) (userMap []interface{}, err error) {
	con := m.conn.Get()
	defer con.Close()
	userMap, err = redis.Values(con.Do("ZRANGE", setname, 0, 10, "WITHSCORES"))
	return
}

func (m *DbRedis) ZRangeDesc(setname string) (userMap []interface{}, err error) {
	con := m.conn.Get()
	defer con.Close()
	userMap, err = redis.Values(con.Do("ZREVRANGE", setname, 0, 10, "WITHSCORES"))
	return
}

func (m *DbRedis) ZDel(setname string, key string) (err error) {
	con := m.conn.Get()
	defer con.Close()
	_, err = con.Do("zrem", setname, key)
	return
}
func (m *DbRedis) ZDelBatch(setname string, keys []string) (err error) {
	con := m.conn.Get()
	defer con.Close()
	_, err = con.Do("zrem", redis.Args{}.Add(setname).AddFlat(keys)...)
	return
}

//命令用于移除有序集中，指定分数（score）区间内的所有成员。
func (m *DbRedis) ZremRangeByscore(setname string, min int64, max int64) (err error) {
	con := m.conn.Get()
	defer con.Close()
	_, err = con.Do("ZREMRANGEBYSCORE", setname, min, max)
	return
}

//返回有序集合的基数
func (m *DbRedis) ZCARD(setname string) (res int, err error) {
	con := m.conn.Get()
	defer con.Close()
	res, err = redis.Int(con.Do("ZCARD", setname))
	return
}

//返回有序集合的基数
func (m *DbRedis) ZAdd(setname string, key int64, value int64) (err error) {
	con := m.conn.Get()
	defer con.Close()
	_, err = con.Do("ZADD", setname, key, value)
	return
}
